/**
 * Created by inZa on 1. 10. 2014.
 *
 * App setting and definitions
 */

angular.module('aaser', [
    'aaser.controllers',
    'aaser.services',
    'aaser.filters',
    'aaser.directives',
    'aaser.models',
    'ngRoute',
    'ngResource',
    'ngCookies',
    'mgcrea.ngStrap',
    'http-auth-interceptor',
    'base64',
    'aaser.appConfig'
]).
    config(['$routeProvider', '$httpProvider', function ($routeProvider) {
        $routeProvider.
            when("/", {templateUrl: "partials/pages/home.html"}).
            when("/login", {templateUrl: "partials/pages/login.html", controller: "LoginController"})



    }]);

angular.module('aaser.controllers', []);
angular.module('aaser.directives', []);
angular.module('aaser.models', []);


/**
 * Created by inZa on 10. 10. 2014.
 */

var aaser ={
        configuration : {
            restApiUrl: 'https://localhost:8443'

        }

} ;

angular.module('aaser.appConfig', []).constant("AppConfig", aaser.configuration);
/**
 * Created by inZa on 2. 10. 2014.
 */

var filterModule = angular.module('aaser.filters', []);

filterModule.filter('ClassificationFilter', function () {
    return function (parent, childName) {
        if (parent != null && childName != null) {

            switch (childName) {

                case 'region':
                    return parent.regions;
                    break;
                case 'site':
                    return parent.sites;
                    break;
                case 'product':
                    return parent.products;
                    break;
                case 'technology':
                    return parent.technologies;
                    break;
                case 'team':
                    return parent.teams;
                    break;
                case 'cell':
                    return parent.cells;
                    break;
                case 'machine':
                    return parent.machines;
                    break;

            }
        }
        return [];
    }
});


filterModule.filter('ldapAssignmentSearch', ['$filter', function ($filter) {
    return function (entities, input, assigned) {
        if (angular.isDefined(input) && angular.isDefined(assigned)) {
            input = input.toLowerCase();
            var filtered = [];
            angular.forEach(entities, function (entity) {
                if (entity.name.toLowerCase().indexOf(input) >= 0 && $filter('filter')(assigned, entity, true).length < 1) filtered.push(entity);
            });
            return filtered;
        }
        if (angular.isDefined(assigned)) {
            var filtered = [];
            angular.forEach(entities, function (entity) {
                if ($filter('filter')(assigned, entity.name, true).length < 1) filtered.push(entity);
            });
            return filtered;
        }
        if (angular.isDefined(input)) {
            input = input.toLowerCase();
            var filtered = [];
            angular.forEach(entities, function (entity) {
                if (entity.name.toLowerCase().indexOf(input) >= 0) filtered.push(entity);
            });
            return filtered;
        }
        return entities;
    }
}]);

filterModule.filter('ldapEntitySearch', ['$filter', function ($filter) {
    return function (entities, input, selected) {
        if (input) {
            if (angular.isDefined(selected)) {
                input = input.toLowerCase();
                var filtered = [];
                if (!angular.isArray(selected)) {
                    selected = new Array(selected);
                }
                angular.forEach(entities, function (entity) {
                    if (entity.name.toLowerCase().indexOf(input) >= 0 && $filter('filter')(selected, {name: entity.name}, true).length < 1) filtered.push(entity);
                });
                return selected.concat(filtered);

            } else {
                input = input.toLowerCase();
                var filtered = [];
                angular.forEach(entities, function (entity) {
                    if (entity.name.toLowerCase().indexOf(input) >= 0)  filtered.push(entity);
                });
                return filtered;
            }
        }
        return entities;
    }
}]);




/**
 * Created by inZa on 3. 10. 2014.
 *
 * Services for communication with rest api
 */
var servicesModule = angular.module('aaser.services', ['ngResource']);


servicesModule.factory('Assignment', function ($resource, AppConfig) {

    return $resource(AppConfig.restApiUrl + '/assignments/:Id',
        {Id: "@Id" });
});


/**
 * Authorization request for user's permissons
 */
servicesModule.factory('Authorization', function ($http, $resource, AppConfig, $location) {

    return function (params) {
        $http.get(AppConfig.restApiUrl + '/authorization', {params: params})
            .success(function (data, status, headers, config) {

            }).error(function (response) {
                $location.path("/");
            });
    }
});
/**
 * Lock service prevents multiple refresh token sending.
 */
servicesModule.service('Lock', function () {
    this.unlock = true;

});
/**
 * Service for handling user's sessions
 */
servicesModule.service('Authentication', function ($resource, $location, $http, UserSession, authService, AppConfig, Lock) {
    function destroyForLogin() {
        authService.loginCancelled();
        UserSession.destroy();
        Lock.unlock = true;
        $location.path("/login");
    }

    this.refreshed = function (data) {
        UserSession.create(data);
        authService.loginConfirmed(null, function (config) {
            config.headers['Authorization'] = 'Bearer ' + UserSession.user.token.accessToken;
            return config;
        });
        Lock.unlock = true;
    };
    this.required = function () {
    };

    this.login = function (credentials) {
        $http.get(AppConfig.restApiUrl + '/authentication/ldap1', {
            headers: {'Authorization': 'Basic ' + credentials }
        }).success(function (data, status) {
            if (status === 200) {
                UserSession.create(data);
                Lock.unlock = true;
                $location.path("/");
            }
        });
    };

    this.cancel = function () {
        destroyForLogin();
    };

    return this;
});
/*
*Service for sending refresh tokens
 */
servicesModule.factory('Refresh', function ($http, UserSession, AppConfig, Authentication, Lock) {
    return function () {

        if (Lock.unlock) {
            if (UserSession.user) {
                if (UserSession.user.token.expires < Date.now()) {
                    Lock.unlock = false;
                    $http.get(AppConfig.restApiUrl + '/token-refresh?token=' + UserSession.user.token.refreshToken)
                        .success(function (data, status, headers, config) {
                            Authentication.refreshed(data);

                        }).error(function (response) {
                            Authentication.cancel();
                        });

                } else {
                    Authentication.cancel();
                }
            } else {
                Authentication.cancel();
            }

        }

    }
});

servicesModule.factory('LdapResources', function ($rootScope, $resource, AppConfig) {
    return {
        groups: $resource(AppConfig.restApiUrl + '/groups'),
        users: $resource(AppConfig.restApiUrl + '/users'),
        roles: $resource(AppConfig.restApiUrl + '/roles'),
        classifications: $resource(AppConfig.restApiUrl + '/classifications')

    }
});


/*
 *   Main controller
 */

angular.module('aaser.controllers').controller('AaserController', ['$rootScope', '$scope', '$location', '$base64', 'Authentication', 'UserSession', 'Authorization', 'Refresh',
    function ($rootScope, $scope, $location, $base64, Authentication, UserSession, Authorization, Refresh) {
        $scope.isSelected = function (page) {
            return page == $location.$$path;
        };

        UserSession.getFromCookie();


        $scope.$on('event:auth-loginRequired', function () {
            Refresh();
        });


        $scope.logout = function () {
            Authentication.cancel();

        }

    }]);
/**
 * Created by inZa on 1. 10. 2014.
 */
angular.module('aaser.controllers').controller('LoginController', ['$rootScope', '$scope', '$base64', 'Authentication','UserSession',
    function ($rootScope, $scope, $base64, Authentication,UserSession) {


    $scope.login = function(){
        var credentials=$scope.name+":"+$scope.pass;
        Authentication.login($base64.encode(credentials));
    };
}]);
/**
 * Checklist-model
 * AngularJS directive for list of checkboxes
 */

angular.module('aaser.directives')
    .directive('checklistModel', ['$parse', '$compile', function($parse, $compile) {
        // contains
        function contains(arr, item) {
            if (angular.isArray(arr)) {
                for (var i = 0; i < arr.length; i++) {
                    if (angular.equals(arr[i], item)) {
                        return true;
                    }
                }
            }
            return false;
        }

        // add
        function add(arr, item) {
            arr = angular.isArray(arr) ? arr : [];
            for (var i = 0; i < arr.length; i++) {
                if (angular.equals(arr[i], item)) {
                    return arr;
                }
            }
            arr.push(item);
            return arr;
        }

        // remove
        function remove(arr, item) {
            if (angular.isArray(arr)) {
                for (var i = 0; i < arr.length; i++) {
                    if (angular.equals(arr[i], item)) {
                        arr.splice(i, 1);
                        break;
                    }
                }
            }
            return arr;
        }


        function postLinkFn(scope, elem, attrs) {
            // compile with `ng-model` pointing to `checked`
            $compile(elem)(scope);

            // getter / setter for original model
            var getter = $parse(attrs.checklistModel);
            var setter = getter.assign;

            // value added to list
            var value = $parse(attrs.checklistValue)(scope.$parent);

            // watch UI checked change
            scope.$watch('checked', function(newValue, oldValue) {
                if (newValue === oldValue) {
                    return;
                }
                var current = getter(scope.$parent);
                if (newValue === true) {
                    setter(scope.$parent, add(current, value));
                } else {
                    setter(scope.$parent, remove(current, value));
                }
            });

            // watch original model change
            scope.$parent.$watch(attrs.checklistModel, function(newArr, oldArr) {
                scope.checked = contains(newArr, value);
            }, true);
        }

        return {
            restrict: 'A',
            priority: 1000,
            terminal: true,
            scope: true,
            compile: function(tElement, tAttrs) {
                if (tElement[0].tagName !== 'INPUT' || !tElement.attr('type', 'checkbox')) {
                    throw 'checklist-model should be applied to `input[type="checkbox"]`.';
                }

                if (!tAttrs.checklistValue) {
                    throw 'You should provide `checklist-value`.';
                }

                // exclude recursion
                tElement.removeAttr('checklist-model');

                // local scope var storing individual checkbox model
                tElement.attr('ng-model', 'checked');

                return postLinkFn;
            }
        };
    }]);
/**
 * Created by inZa on 2. 10. 2014.
 */
angular.module('aaser.directives').directive('confirmationPopup', function () {
    return {
        templateUrl: '/partials/templates/confirmationPopup.tmpl.html',
        link: function (scope, element, attrs) {

        }

    };
});
/**
 * Created by inZa on 6. 10. 2014.
 *
 * User singleton that contains tokens and username
 */
angular.module('aaser.models').service('UserSession', function ($cookieStore, $http) {
    this.user = null;
    this.create = function (authUser) {
        this.user = {};
        this.user.name = authUser.user.name;
        this.user.type = authUser.user.type;
        this.user.token = authUser.tokenInfo;
        $cookieStore.put('user', this.user);
        this.setHeaders();
    };

    this.getFromCookie = function () {
        if (angular.isDefined($cookieStore.get('user'))) {
            this.user = $cookieStore.get('user');
            this.setHeaders();
        }
    };

    this.setHeaders = function () {
        $http.defaults.headers.common['Authorization'] = 'Bearer ' + this.user.token.accessToken;

    };


    this.destroy = function () {
        this.user = null;
        $cookieStore.remove('user');
    };
    return this;
});